package controllers

import (
	"encoding/json"
	"fmt"
	"github.com/stretchr/testify/assert"
	"gitverse.ru/synapse/kubelatte/pkg/api/v1alpha1"
	"gitverse.ru/synapse/kubelatte/pkg/util"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"testing"
)

func TestSelector(t *testing.T) {
	data, _ := json.Marshal(&util.NamespaceSelector{
		LabelSelector: metav1.LabelSelector{
			MatchExpressions: []metav1.LabelSelectorRequirement{
				metav1.LabelSelectorRequirement{
					Key:      "test",
					Operator: "In",
					Values:   []string{"aaaa"},
				},
			},
		},
		Include: []string{"incExample"},
		Exclude: []string{"exExample"},
	})

	fmt.Println(string(data))
}

func TestInitEnv(t *testing.T) {
	PrometheusInit()
	NamespaceSelectorCommonResource = "{\"labelSelector\": {\"matchExpressions\": [{\"key\":\"kubelatte-injection\",\"operator\": \"In\",\"values\": [\"enabled\"]}]}}"
	InitEnv()
	assert.Equal(t, "kblt.creation.resource", KbltCreatorLabelKey)
}

func TestUtils(t *testing.T) {
	GetShortHash("123")
	GetRandomPart()
	KbltCreator = "true"
	IsCreatorRole()
	KbltCreator = "false"
	IsCreatorRole()
	KbltMutator = "true"
	IsMutatorRole()
	KbltMutator = "false"
	IsMutatorRole()
	KbltValidator = "true"
	IsValidatorRole()
	KbltValidator = "false"
	IsValidatorRole()
	KbltCreator = "true"
	KbltMutator = "true"
	KbltValidator = "true"
	IsFullRole()
	KbltCreator = "false"
	KbltMutator = "true"
	KbltValidator = "true"
	IsFullRole()
	CreationMode = "cluster"
	IsCreationInClusterMode()
	CreationMode = "local"
	IsCreationInClusterMode()
	LocalNamespaceMode = "true"
	IsOperatorInClusterMode()
	LocalNamespaceMode = "false"
	IsOperatorInClusterMode()
	KbltCreator = "true"
	KbltMutator = "true"
	KbltValidator = "true"
	IsControllerNeeded("scope")
	IsControllerNeeded("trigger")
	IsControllerNeeded("template")
	IsControllerNeeded("triggerInstance")
	KbltCreator = "false"
	KbltMutator = "false"
	KbltValidator = "false"
	IsControllerNeeded("scope")
	IsControllerNeeded("trigger")
	IsControllerNeeded("template")
	IsControllerNeeded("triggerInstance")
}

func Test_removeCondition(t *testing.T) {
	type args struct {
		conditions []v1alpha1.Condition
		ct         v1alpha1.ConditionType
	}
	tests := []struct {
		name string
		args args
		want []v1alpha1.Condition
	}{
		{
			name: "with removable conditions",
			args: args{
				conditions: []v1alpha1.Condition{
					{
						Type: "RemoveIt",
					},
				},
				ct: "RemoveIt",
			},
			want: []v1alpha1.Condition{},
		},
		{
			name: "without removable conditions",
			args: args{
				conditions: []v1alpha1.Condition{
					{
						Type: "DontRemoveIt",
					},
				},
				ct: "RemoveIt",
			},
			want: []v1alpha1.Condition{
				{
					Type: "DontRemoveIt",
				},
			},
		},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			assert.Equalf(t, tt.want, removeCondition(tt.args.conditions, tt.args.ct), "removeCondition(%v, %v)", tt.args.conditions, tt.args.ct)
		})
	}
}

func TestGetOwnerRef(t *testing.T) {
	type args struct {
		obj map[string]interface{}
	}
	tests := []struct {
		name    string
		args    args
		want    *metav1.OwnerReference
		wantErr error
	}{
		{
			name: "without metadata",
			args: args{
				obj: map[string]interface{}{
					"spec": "str",
				},
			},
			want:    nil,
			wantErr: fmt.Errorf("GetOwnerRef failed. Metadata not found"),
		},
		{
			name: "without name",
			args: args{
				obj: map[string]interface{}{
					"metadata": map[string]interface{}{
						"test": "test",
					},
				},
			},
			want:    nil,
			wantErr: fmt.Errorf("GetOwnerRef failed. Name not found"),
		},
		{
			name: "without uid",
			args: args{
				obj: map[string]interface{}{
					"metadata": map[string]interface{}{
						"name": "test",
					},
				},
			},
			want:    nil,
			wantErr: fmt.Errorf("GetOwnerRef failed. UID not found"),
		},
		{
			name: "without apiVersion",
			args: args{
				obj: map[string]interface{}{
					"metadata": map[string]interface{}{
						"name": "test",
						"uid":  "uid",
					},
				},
			},
			want:    nil,
			wantErr: fmt.Errorf("GetOwnerRef failed. ApiVersion not found"),
		},
		{
			name: "without kind",
			args: args{
				obj: map[string]interface{}{
					"apiVersion": "test",
					"metadata": map[string]interface{}{
						"name": "test",
						"uid":  "uid",
					},
				},
			},
			want:    nil,
			wantErr: fmt.Errorf("GetOwnerRef failed. Kind not found"),
		},
		{
			name: "ok",
			args: args{
				obj: map[string]interface{}{
					"kind":       "test",
					"apiVersion": "test",
					"metadata": map[string]interface{}{
						"name": "test",
						"uid":  "uid",
					},
				},
			},
			want: &metav1.OwnerReference{
				APIVersion: "test",
				Kind:       "test",
				Name:       "test",
				UID:        "uid",
			},
			wantErr: nil,
		},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			got, err := GetOwnerRef(tt.args.obj)
			if err != tt.wantErr {
				return
			}
			assert.Equalf(t, tt.want, got, "GetOwnerRef(%v)", tt.args.obj)
		})
	}
}
